/*
Package unifiedcode 按照GB 32100-2015标准校验法人和其他组织统一社会信用代码.

统一代码由十八位的阿拉伯数字或大写英文字母（不适用I、O、Z、S、V）组成，包括第1位的登记管理部门代码、第2位机构类别代码、第3位~第8位登记管理机关行政区划吗、第9位~第17位主体标识码（组织机构代码）、第18位校验码五个部分。具体形式如下:

	| 代码序号 | 代码 | 说明 |
	| --- | --- | --- |
	|  1  | X |登记管理部门代码1位 |
	|  2  | X | 机构类别代码1位 |
	| 3~8 | XXXXXX |登记管理机关行政区划码6位 |
	| 9~17| 主体标识码（组织机构码）9位 |
	| 18  | 校验码1位 |

校验码计算规则：C_{18} = 31 - MOD(\sum_{i=1}^{17}(C_i{x}W_i),31)

*/
package unifiedcode

var (
	// 前17位字符的权重
	weights = [17]int{1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28}
	// 代码字符表
	codes = map[byte]int{
		'0': 0, '1': 1, '2': 2, '3': 3, '4': 4,
		'5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
		'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14,
		'F': 15, 'G': 16, 'H': 17, 'J': 18, 'K': 19,
		'L': 20, 'M': 21, 'N': 22, 'P': 23, 'Q': 24,
		'R': 25, 'T': 26, 'U': 27, 'W': 28, 'X': 29,
		'Y': 30,
	}
)

func sum(s []byte) int {
	var sum int
	for i := 0; i < len(s); i++ {
		sum += codes[s[i]] * weights[i]
	}
	return sum
}

func checkCode(s []byte) int {
	return 31 - sum(s)%31
}

// Validate 校验统一代码
func Validate(b []byte) bool {
	if len(b) != 18 {
		return false
	}
	return checkCode(b[:17]) == codes[b[17]]
}
